// package关键字：用于声明包路径，将相关类组织在一起
// com.itheima.polymorphsm2：包名，表示这个类所在的位置
package com.itheima.polymorphsm2;

// public：访问修饰符，表示这个类可以被其他任何类访问
// class：定义类的关键字
// Test：类名，这是一个测试类，用于演示多态的概念
public class Test {
    // public：访问修饰符，表示这个方法可以被任何类调用
    // static：静态修饰符，表示这个方法属于类，不需要创建对象就可以调用
    // void：返回值类型，表示这个方法不返回任何值
    // main：方法名，这是Java程序的入口方法，程序从这里开始执行
    // String[] args：参数列表，表示程序可以接收命令行参数
    public static void main(String[] args) {
        // 目标：认识多态的代码。
        // 多态是面向对象编程的重要特性，允许不同子类对同一方法有不同的实现

        // 1、多态的好处1: 右边对象是解耦合的。
        // 解耦合意味着我们可以轻松替换右边的实现，而不影响左边的代码
        // Animal：父类类型
        // a1：变量名
        // =：赋值运算符
        // new Tortoise()：创建Tortoise子类的对象
        // 这行代码体现了多态的核心：父类引用指向子类对象
        // 左边是父类类型，右边是子类实例
        Animal a1 = new Tortoise();
        // a1.run()：调用run方法
        // 多态下方法调用的规则：编译看左边（父类是否有这个方法），运行看右边（执行子类的实现）
        // 这里实际执行的是Tortoise类中重写的run方法
        a1.run();
        // a1.shrinkHead(); // 多态下的一个问题：多态下不能调用子类独有功能。
        // 这行代码会报错，因为父类Animal中没有shrinkHead()方法
        // 多态限制：父类引用只能调用父类中定义的方法，不能直接调用子类特有的方法

        // Wolf：子类类型
        // w：变量名
        // new Wolf()：创建Wolf类的对象
        // 这是普通的对象创建方式，没有体现多态
        Wolf w = new Wolf();
        // 调用go方法，并传入Wolf对象作为参数
        // 虽然go方法参数是Animal类型，但可以接收Wolf对象
        // 这体现了多态的另一个好处：父类类型可以接收任何子类对象
        go(w);

        // Tortoise：子类类型
        // t：变量名
        // new Tortoise()：创建Tortoise类的对象
        Tortoise t = new Tortoise();
        // 调用go方法，并传入Tortoise对象作为参数
        // 同样体现了多态的好处：同一个go方法可以处理不同的子类对象
        go(t);
    } // main方法结束

    // 宠物游戏：所有动物都可以送给这个方法开始跑步。
    // 2、多态的好处2：父类类型的变量作为参数，可以接收一个子类对象
    // 这样可以大大提高代码的扩展性和复用性
    // public：访问修饰符
    // static：静态修饰符，可以直接通过类名调用
    // void：返回值类型
    // go：方法名
    // Animal a：参数，类型是Animal父类，可以接收任何Animal的子类对象
    public static void go(Animal a){
        // 输出提示信息
        System.out.println("开始。。。。。");
        // 调用传入对象的run方法
        // 多态机制：根据实际传入的对象类型，执行对应的run方法
        // 如果传入Wolf对象，执行Wolf的run方法
        // 如果传入Tortoise对象，执行Tortoise的run方法
        a.run();
        // a1.shrinkHead(); // 报错，多态下不能调用子类独有功能。
        // 同样的限制：在go方法中也不能调用子类特有的方法
    } // go方法结束
} // Test类结束
